import React, { useCallback, useEffect, useRef } from "react";
import Matter from "matter-js";
import style from "./physicsEngine.module.scss";
const PhysicsEngine = () => {
  const canvasRef = useRef();
  const canvasContainerRef = useRef();

  // 初始化canvas尺寸
  useEffect(() => {
    const { clientWidth, clientHeight } = canvasContainerRef.current;
    canvasRef.current.width = clientWidth;
    canvasRef.current.height = clientHeight;
  }, []);

  // 使用matter-js物理引擎画canvas
  useEffect(() => {
    const {
      Mouse,
      Engine,
      Render,
      Bodies,
      Runner,
      Common,
      Composite,
      Composites,
      MouseConstraint,
    } = Matter;

    // create engine
    const engine = Engine.create(),
      world = engine.world;

    // create renderer
    const render = Render.create({
      engine,
      canvas: canvasRef.current,
      options: {
        width: canvasRef.current.width,
        height: canvasRef.current.height,
        showVelocity: true,
        showAngleIndicator: true,
      },
    });

    Render.run(render);

    // create runner
    const runner = Runner.create();
    Runner.run(runner, engine);

    // add bodies
    Composite.add(world, [
      Bodies.rectangle(400, 0, 800, 50, { isStatic: true }),
      Bodies.rectangle(400, 600, 800, 50.5, { isStatic: true }),
      Bodies.rectangle(800, 300, 50, 600, { isStatic: true }),
      Bodies.rectangle(0, 300, 50, 600, { isStatic: true }),
    ]);

    // 修改y轴重力分量
    engine.gravity.y = 0.1;

    // 生成一堆刚体
    const stack = Composites.stack(50, 120, 11, 5, 0, 0, function (x, y) {
      switch (Math.round(Common.random(0, 1))) {
        case 0:
          if (Common.random() < 0.8) {
            return Bodies.rectangle(
              x,
              y,
              Common.random(20, 50),
              Common.random(20, 50)
            );
          } else {
            return Bodies.rectangle(
              x,
              y,
              Common.random(80, 120),
              Common.random(20, 30)
            );
          }
        case 1:
          return Bodies.polygon(
            x,
            y,
            Math.round(Common.random(1, 8)),
            Common.random(20, 50)
          );
        default:
          break;
      }
    });

    // 将堆放到世界中
    Composite.add(world, stack);

    // add mouse control
    const mouse = Mouse.create(render.canvas),
      mouseConstraint = MouseConstraint.create(engine, {
        mouse: mouse,
        constraint: {
          stiffness: 0.2,
          render: {
            visible: false,
          },
        },
      });

    Composite.add(world, mouseConstraint);

    // keep the mouse in sync with rendering
    render.mouse = mouse;

    // fit the render viewport to the scene
    Render.lookAt(render, {
      min: { x: 0, y: 0 },
      max: { x: 800, y: 600 },
    });

    // 清除
    return () => {
      Engine.clear(engine);
      Render.stop(render);
      Render.endViewTransform(render);
    };
  }, []);
  return (
    <div className={style.canvasContainer} ref={canvasContainerRef}>
      <canvas id={style.canvas} ref={canvasRef} />
    </div>
  );
};

export default PhysicsEngine;
